﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Text;
using LogManager.Base;
using LogManager.Base.Data;

namespace LogManager.Windows
{
    public static class WindowsEventMapper
    {
        public static IEvent MapEvent(IEvent @event, EventRecord record)
        {
            //Map special event properties
            var properties = record.GetEventProperties();

            //Map standard event properties
            MapEventStandardProperties(@event, record,properties);
            
            @event.UndefinedProperties = record.GetUndefinedEventProperties();

            if (properties != null && properties.Count > 0)
            {
                MapEventProperties(@event, properties);
            }           

            return @event;
        }

        /// <summary>
        /// Maps the standard properties of IEvent
        /// </summary>
        /// <param name="event">The event to map to</param>
        /// <param name="record">The record to map from</param>
        /// <param name="properties">Properties extracted from record</param>
        private static void MapEventStandardProperties(IEvent @event, EventRecord record, IDictionary<string, string> properties)
        {
            @event.Type = record.Id.ToString();
            @event.Id = record.RecordId.ToString();
            @event.Level = WindowsEventLevelHelper.GetLevel(record.Level);
            @event.Message = GetMessage(record) ?? properties.GetValueOrDefault("Message",null);
            //Set to now if timestamp not set
            @event.TimeStamp = record.TimeCreated.HasValue ? record.TimeCreated.Value : DateTime.Now;

            try
            {
                @event.User = record.UserId == null ? string.Empty : record.UserId.ToString();

            }
            catch (Exception)
            {
                //Suppress because security identifier is sometimes forbidden
            }
        }

        /// <summary>
        /// Extracts a message out of a record
        /// </summary>
        /// <param name="record">The record that holds the message</param>
        /// <returns>Event message</returns>
        private static string GetMessage(EventRecord record)
        {
            //note: poor performance but rich information approach
            try
            {
                return record.FormatDescription();
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Maps event properties based on the event type
        /// </summary>
        /// <param name="event">Event to map to</param>
        /// <param name="properties">Properties to map from</param>
        private static void MapEventProperties(IEvent @event, IDictionary<string, string> properties)
        {
            foreach (var prop in properties)
            {
                @event.Properties[prop.Key] = prop.Value;
            }
        }
    }
}
